﻿using Microsoft.Extensions.Caching.Distributed;
using NLog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using EssentialWebFramework.Models.Framework;
using EssentialWebFramework.Utils;
using static EssentialWebFramework.Models.Framework.GlobalReadOnlyVariables;

namespace Microsoft.Extensions.Caching.Distributed
{
    public static class MDistributedCacheExtension
    {
        /// <summary>
        /// logger
        /// </summary>
        private static readonly Logger logger = LogManager.GetCurrentClassLogger();

        /// <summary>
        /// 设置空缓存
        /// </summary>
        public static string NULL_CACHE_VALUE = string.Empty;

        /// <summary>
        /// 空缓存的过期时间
        /// </summary>
        public static int NULL_CACHE_TTL_MINUTES = 1;

        /// <summary>
        /// 将对象设置到缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cache"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="absoluteExpireMinutes"></param>
        public static void SetToDistributedCache<T>(this IDistributedCache cache, string key, T value, int absoluteExpireMinutes = 30)
        {
            string mValue = value is string ? value as string : JsonUtils.JsonSerializeForCache(value);
            cache.SetString(key, mValue, new DistributedCacheEntryOptions
            {
                AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(absoluteExpireMinutes)
            });
        }

        /// <summary>
        /// 从缓存中获取对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cache"></param>
        /// <param name="key"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        public static bool TryGetFromDistributedCache<T>(this IDistributedCache cache, string key, out T t)
            where T : new()
        {
            t = default(T);

            string jsonStr = cache.GetString(key);
            
            // 没有找到缓存
            if (jsonStr == null)
            {
                return false;
            }
            // 找到缓存了但缓存内容为空字符串
            else if (jsonStr == string.Empty)
            {
                return true;
            }
            else
            {
                try
                {
                    var result = JsonUtils.JsonDeserializeForCache<T>(jsonStr);
                    if (result == null)
                    {
                        return false;
                    }
                    else
                    {
                        t = result;
                        return true;
                    }
                }
                catch (Exception ex)
                {
                    logger.Error(ex);
                    return false;
                }
            }
        }

        /// <summary>
        /// 将对象设置到缓存（带逻辑过期时间）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cache"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="absoluteExpireMinutes"></param>
        public static void SetToDistributedCacheWithExpire<T>(this IDistributedCache cache, string key, T value, int absoluteExpireMinutes = 30)
        {
            string mValue;
            if(value is string)
            {
                mValue = JsonUtils.JsonSerializeForCache(new RedisValueWithExpire<string>
                {
                    Value = value as string,
                    ExpireTime = DateTime.Now.AddMinutes(absoluteExpireMinutes)

                });
            }
            else
            {
                mValue = JsonUtils.JsonSerializeForCache(new RedisValueWithExpire<T>
                {
                    Value = value,
                    ExpireTime = DateTime.Now.AddMinutes(absoluteExpireMinutes)

                });
            }
            cache.SetString(key, mValue);
        }

        /// <summary>
        /// 从缓存中获取对象（带逻辑过期时间）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cache"></param>
        /// <param name="key"></param>
        /// <param name="isExpired"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        public static bool TryGetFromDistributedCacheWithExpire<T>(this IDistributedCache cache, string key, out bool isExpired, out T t)
            where T : new()
        {
            isExpired = true;
            t = default(T);

            string jsonStr = cache.GetString(key);

            // 没有找到缓存
            if (jsonStr == null)
            {
                return false;
            }
            // 找到缓存了但缓存内容为空字符串
            else if (jsonStr == string.Empty)
            {
                return true;
            }
            else
            {
                try
                {
                    var result = JsonUtils.JsonDeserializeForCache<RedisValueWithExpire<T>>(jsonStr);
                    if (result == null)
                    {
                        return false;
                    }

                    isExpired = DateTime.Now >= result.ExpireTime;
                    
                    t = result.Value;
                    return true;
                }
                catch (Exception ex)
                {
                    logger.Error(ex);
                    return false;
                }
            }
        }
    }
}
